/**
 * nghilt
 * 2011/09/26
 */
package vn.nnn.shogi.quanco;

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.ImageObserver;
import java.lang.reflect.Constructor;
import java.util.ArrayList;

import javax.swing.JApplet;
import javax.swing.JOptionPane;

import at.com.vn.chess.entity.ChatUser;
import at.com.vn.chess.entity.ChessBoardInfo;
import at.com.vn.chess.entity.H;
import at.com.vn.chess.util.CommonMethod;
import at.com.vn.chess.util.Const;
import at.com.vn.chess.util.Msg;

import vn.com.bip.office.smart.util.XMLHelper;
import vn.nnn.shogi.board.Board;

/**
 * 
 */
public class ListQuanCoStatus {

	private ArrayList<QuanCo> mListQuanCo;
	private ArrayList<QuanCo> listQuanCoForHistory;
	private ArrayList<QuanCo> listQuanCoWhenInit;
	private Board board;
	private Rectangle[][] banCo;
	private JApplet mainApplet;

	private ArrayList<Rectangle> repaintArea;
	private ArrayList<Rectangle> currentStepHistory;
	private ArrayList<H> listH;
	private int step;

	ArrayList<String> boardHistory;

	String roomId;
	int tableId;
	boolean normalDirection;
	
	public ListQuanCoStatus( String roomId, int tableId, Board board,
			boolean normalDirection, JApplet mainApplet ) {
		this( board, normalDirection, mainApplet );

		this.roomId = roomId;
		this.tableId = tableId;
	}

	public ListQuanCoStatus( Board board, boolean normalDirection,
			JApplet mainApplet ) {

		this.board = board;
		mListQuanCo = new ArrayList<QuanCo>();
		listH = new ArrayList<H>();
		banCo = board.getRealBoard();
		this.mainApplet = mainApplet;
		this.normalDirection = normalDirection;

		repaintArea = new ArrayList<Rectangle>();
		currentStepHistory = new ArrayList<Rectangle>();

		boardHistory = new ArrayList<String>();

		// TODO xoa sau khi xong
//				forTest();

		// Khoi tao quan co
		QuanCo quanCo = null;
		int[] rowArray = { 0, 1, 2, 6, 7, 8 };
		int row;
		for ( int k = 0; k < rowArray.length; k++ ) {
			row = rowArray[k];
			if ( row != 1 && row != 7 ) {
				for ( int l = 0; l < Const.REAL_BOARD_COL; l++ ) {
					quanCo = initQuanCo( row, l, normalDirection, mainApplet );
					mListQuanCo.add( quanCo );
				}
			} else {
				int colArray[] = { 1, 7 };
				for ( int l = 0; l < colArray.length; l++ ) {
					quanCo = initQuanCo( row, colArray[l], normalDirection, mainApplet );
					mListQuanCo.add( quanCo );
				}
			}
		}
		
		// Copy listQuanCo
		listQuanCoForHistory = clone();
		listQuanCoWhenInit = clone();
	}
	
	private QuanCo initQuanCo( int rowIndex, int colIndex,
			boolean normalDirection, JApplet codeBase ) {
		QuanCo quanCo = null;

		// Set mau sac cho quan co
		int color = QuanCo.QUAN_TRANG;

		if ( normalDirection ) {
			if ( rowIndex > 4 ) {
				color = QuanCo.QUAN_DEN;
			}
		} else {
			if ( rowIndex < 4 ) {
				color = QuanCo.QUAN_DEN;
			}
		}

		// Khoi tao quan co theo hang va cot
		if ( rowIndex == 1 || rowIndex == 7 ) {
			if ( colIndex == rowIndex ) {
//				quanCo = new QuanXe( banCo[rowIndex][colIndex], color,
//						normalDirection, codeBase );
				quanCo = new QX( banCo[rowIndex][colIndex], color,
						normalDirection, codeBase );				
			} else {
				quanCo = new QTi( banCo[rowIndex][colIndex], color,
						normalDirection, codeBase );
			}
		} else if ( rowIndex == 2 || rowIndex == 6 ) {
			quanCo = new QT( banCo[rowIndex][colIndex], color,
					normalDirection, codeBase );
		} else {
			switch ( colIndex ) {
				case 0:
				case 8:
					quanCo = new QHX( banCo[rowIndex][colIndex], color,
							normalDirection, codeBase );
					break;
				case 1:
				case 7:
					quanCo = new QM( banCo[rowIndex][colIndex], color,
							normalDirection, codeBase );
					break;
				case 2:
				case 6:
					quanCo = new QTB( banCo[rowIndex][colIndex], color,
							normalDirection, codeBase );
					break;
				case 3:
				case 5:
					quanCo = new QTV( banCo[rowIndex][colIndex], color,
							normalDirection, codeBase );
					break;
				case 4:
					quanCo = new QV( banCo[rowIndex][colIndex], color,
							normalDirection, codeBase );
					break;
			}
		}
		return quanCo;
	}

	public void forTest() {
		boardHistory
				.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><name>QuanTot</name><oldX>0</oldX><oldY>0</oldY><newX>0</newX><newY>0</newY><c>1</c><p>0</p><rId>room1</rId><tId>1</tId><idx>0</idx></H></Hist>" );

		// Test truong hop binh thuong
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>385</oldY><newX>357</newX><newY>330</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>23</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>165</oldY><newX>357</newX><newY>220</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>14</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>330</oldY><newX>357</newX><newY>275</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>23</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>220</oldY><newX>357</newX><newY>275</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>14</idx></H><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>275</oldY><newX>51</newX><newY>55</newY><oldC>1</oldC><newC>0</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>23</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>561</oldX><oldY>440</oldY><newX>357</newX><newY>440</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>30</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>306</oldX><oldY>165</oldY><newX>306</newX><newY>220</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>13</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>275</oldY><newX>765</newX><newY>495</newY><oldC>0</oldC><newC>1</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>14</idx></H><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>357</oldX><oldY>440</oldY><newX>357</newX><newY>275</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>30</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>51</oldX><oldY>55</oldY><newX>357</newX><newY>220</newY><oldC>0</oldC><newC>0</newC><oldTb>1</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>23</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>220</oldY><newX>765</newX><newY>495</newY><oldC>0</oldC><newC>1</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>23</idx></H><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>357</oldX><oldY>275</oldY><newX>357</newX><newY>220</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>30</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>306</oldX><oldY>220</oldY><newX>306</newX><newY>275</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>13</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>765</oldX><oldY>495</oldY><newX>357</newX><newY>275</newY><oldC>1</oldC><newC>1</newC><oldTb>1</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>14</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>306</oldX><oldY>275</oldY><newX>306</newX><newY>330</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>13</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTuongVang</oldN><newN>QuanTuongVang</newN><oldX>357</oldX><oldY>55</oldY><newX>714</newX><newY>440</newY><oldC>0</oldC><newC>1</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>3</idx></H><H><oldN>QuanXe</oldN><newN>QuanXePhongCap</newN><oldX>357</oldX><oldY>220</oldY><newX>357</newX><newY>55</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>30</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanVua</oldN><newN>QuanVua</newN><oldX>408</oldX><oldY>55</oldY><newX>357</newX><newY>55</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>4</idx></H><H><oldN>QuanXePhongCap</oldN><newN>QuanXe</newN><oldX>357</oldX><oldY>55</oldY><newX>102</newX><newY>165</newY><oldC>1</oldC><newC>0</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>30</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>275</oldY><newX>357</newX><newY>220</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>14</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>255</oldX><oldY>110</oldY><newX>357</newX><newY>110</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>9</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QTPCp</newN><oldX>357</oldX><oldY>220</oldY><newX>357</newX><newY>165</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>14</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>357</oldX><oldY>110</oldY><newX>357</newX><newY>165</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>9</idx></H><H><oldN>QTPCp</oldN><newN>QuanTot</newN><oldX>357</oldX><oldY>165</oldY><newX>51</newX><newY>55</newY><oldC>1</oldC><newC>0</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>14</idx></H></Hist>" );
//		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>765</oldX><oldY>495</oldY><newX>357</newX><newY>220</newY><oldC>1</oldC><newC>1</newC><oldTb>1</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>23</idx></H></Hist>" );

		// Test truong hop dao nguoc
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>165</oldY><newX>459</newX><newY>220</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>16</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>385</oldY><newX>459</newX><newY>330</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>25</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>220</oldY><newX>459</newX><newY>275</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>16</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>275</oldY><newX>765</newX><newY>495</newY><oldC>1</oldC><newC>0</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>16</idx></H><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>330</oldY><newX>459</newX><newY>275</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>25</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>255</oldX><oldY>110</oldY><newX>459</newX><newY>110</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>9</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>510</oldX><oldY>385</oldY><newX>510</newX><newY>330</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>26</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>459</oldX><oldY>110</oldY><newX>459</newX><newY>275</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>9</idx></H><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>275</oldY><newX>51</newX><newY>55</newY><oldC>0</oldC><newC>1</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>25</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>765</oldX><oldY>495</oldY><newX>459</newX><newY>330</newY><oldC>0</oldC><newC>0</newC><oldTb>1</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>16</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>459</oldX><oldY>275</oldY><newX>459</newX><newY>330</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>9</idx></H><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>330</oldY><newX>51</newX><newY>55</newY><oldC>0</oldC><newC>1</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>16</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>510</oldX><oldY>330</oldY><newX>510</newX><newY>275</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>26</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>51</oldX><oldY>55</oldY><newX>459</newX><newY>275</newY><oldC>1</oldC><newC>1</newC><oldTb>1</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>25</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>510</oldX><oldY>275</oldY><newX>510</newX><newY>220</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>26</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXePhongCap</newN><oldX>459</oldX><oldY>330</oldY><newX>459</newX><newY>495</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>9</idx></H><H><oldN>QuanTuongVang</oldN><newN>QuanTuongVang</newN><oldX>459</oldX><oldY>495</oldY><newX>102</newX><newY>110</newY><oldC>0</oldC><newC>1</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>36</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXePhongCap</oldN><newN>QuanXe</newN><oldX>459</oldX><oldY>495</oldY><newX>714</newX><newY>385</newY><oldC>1</oldC><newC>0</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>9</idx></H><H><oldN>QuanVua</oldN><newN>QuanVua</newN><oldX>408</oldX><oldY>495</oldY><newX>459</newX><newY>495</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>35</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>275</oldY><newX>459</newX><newY>330</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>25</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>561</oldX><oldY>440</oldY><newX>459</newX><newY>440</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>30</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QTPCp</newN><oldX>459</oldX><oldY>330</oldY><newX>459</newX><newY>385</newY><oldC>1</oldC><newC>1</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>25</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QTPCp</oldN><newN>QuanTot</newN><oldX>459</oldX><oldY>385</oldY><newX>765</newX><newY>495</newY><oldC>1</oldC><newC>0</newC><oldTb>0</oldTb><newTb>1</newTb><rId>room1</rId><tId>1</tId><idx>25</idx></H><H><oldN>QuanXe</oldN><newN>QuanXe</newN><oldX>459</oldX><oldY>440</oldY><newX>459</newX><newY>385</newY><oldC>0</oldC><newC>0</newC><oldTb>0</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>30</idx></H></Hist>" );
		boardHistory.add( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><Hist><H><oldN>QuanTot</oldN><newN>QuanTot</newN><oldX>51</oldX><oldY>55</oldY><newX>459</newX><newY>330</newY><oldC>1</oldC><newC>1</newC><oldTb>1</oldTb><newTb>0</newTb><rId>room1</rId><tId>1</tId><idx>16</idx></H></Hist>" );

		setCurrentStep();
	}
	
	public void drawListQuanCo( Graphics g, boolean readyToMove ) {

		// ve vung bat
		// board.veVungBatQuan( g );
		board.veVungBatQuan2( g );

		// Ve cac quan co
		for ( int i = 0; i < mListQuanCo.size(); i++ ) {
			mListQuanCo.get( i ).drawQuanCo( g, mainApplet );
		}

		// Ve nhung nuoc da di
		if ( !readyToMove ) {
			for ( Rectangle rect : currentStepHistory ) {
				g.drawRect( rect.x, rect.y, rect.width, rect.height );
			}
		}
	}
	
	public void drawListQuanCoForHistory( Graphics g, ImageObserver imgObserver ) {

		// ve vung bat
		// board.veVungBatQuan( g );
		board.veVungBatQuan2( g );

		// Ve cac quan co
		for ( int i = 0; i < listQuanCoForHistory.size(); i++ ) {
			listQuanCoForHistory.get( i ).drawQuanCo( g, imgObserver );
		}
	}

	public void makeSymmetry() {
		Rectangle rect;
		for ( QuanCo quanCo : mListQuanCo ) {
			rect = quanCo.toaDo;
			quanCo.toaDo = board.makeSymmetry( rect );
			Image temp = quanCo.pic;
			quanCo.pic = quanCo.enemyPic;
			quanCo.enemyPic = temp;
		}
	}

	public void makeSymmetryView() {
		for ( QuanCo quanCo : mListQuanCo ) {
			Image temp = quanCo.pic;
			quanCo.pic = quanCo.enemyPic;
			quanCo.enemyPic = temp;
		}
	}

	private ArrayList<QuanCo> tempListQuanCo;

	public String convertSymmetryBoardToXMLString( String processName,
			ChatUser user, int isTablesOwner, String status, int turn, String blackName,
			String whiteName, int blackRemainTime, int whiteRemainTime, int whosWon ) {
		ArrayList<ChessBoardInfo> listInfoObject = new ArrayList<ChessBoardInfo>();
		ChessBoardInfo infoObject;

		tempListQuanCo = clone();

		// Dao nguoc idx cua ban co
		ArrayList<QuanCo> temp = new ArrayList<QuanCo>();
		
		for( int i = tempListQuanCo.size() - 1; i >= 0; i-- ) {
			temp.add( tempListQuanCo.get( i ) );
		}
		
		tempListQuanCo = temp;

		for ( QuanCo quanCo : tempListQuanCo ) {
			Rectangle rect = quanCo.toaDo;
			rect = board.makeSymmetry( rect );

			quanCo.setToaDo( rect );

			infoObject = new ChessBoardInfo( status, turn, blackName, whiteName,
					blackRemainTime, whiteRemainTime, whosWon, user, isTablesOwner, quanCo );
			listInfoObject.add( infoObject );
		}

		return XMLHelper
				.convertListObjectToXML( listInfoObject, processName, ChessBoardInfo.class );
	}

	/**
	 * Chuyen trang thai toan ban co sang String
	 * 
	 * @param roomId
	 * @param tableId
	 * @param status
	 * @param turn
	 * @return
	 */
	public String convertToXMLString( String processName, ChatUser user, int isTablesOwner,
			String status, int turn, String blackName, String whiteName,
			int blackRemainTime, int whiteRemainTime, int whosWon ) {

		ArrayList<ChessBoardInfo> listInfoObject = new ArrayList<ChessBoardInfo>();
		ChessBoardInfo infoObject;
		QuanCo quanCo;

		for ( int i = 0; i < mListQuanCo.size(); i++ ) {
			quanCo = mListQuanCo.get( i );

			infoObject = new ChessBoardInfo( status, turn, blackName, whiteName,
					blackRemainTime, whiteRemainTime, whosWon, user, isTablesOwner, quanCo );
			listInfoObject.add( infoObject );
		}

		return XMLHelper
				.convertListObjectToXML( listInfoObject, processName, ChessBoardInfo.class );
	}

	public String convertToXMLString( String processName, ChatUser user,
			String status, int turn, int whosWon ) {

		return convertToXMLString( mListQuanCo, processName, user, status, turn, whosWon );
	}
	
	public String convertToXMLString( ArrayList<QuanCo> listQuanCo, String processName, ChatUser user,
			String status, int turn, int whosWon ) {
		ArrayList<ChessBoardInfo> listInfoObject = new ArrayList<ChessBoardInfo>();
		ChessBoardInfo infoObject;
		QuanCo quanCo;

		for ( int i = 0; i < listQuanCo.size(); i++ ) {
			quanCo = listQuanCo.get( i );

			infoObject = new ChessBoardInfo( status, turn, whosWon, user, quanCo );
			listInfoObject.add( infoObject );
		}

		return XMLHelper
				.convertListObjectToXML( listInfoObject, processName, ChessBoardInfo.class );
	}

	@Deprecated
	private String convertToXMLString( ArrayList<QuanCo> listQuanCo,
			String processName, ChatUser user, String player1Name,
			String player2Name, String status, int turn, int whosWon ) {
		
		ArrayList<ChessBoardInfo> listInfoObject = new ArrayList<ChessBoardInfo>();
		ChessBoardInfo infoObject;
		QuanCo quanCo;

		for ( int i = 0; i < listQuanCo.size(); i++ ) {
			quanCo = listQuanCo.get( i );

			infoObject = new ChessBoardInfo( status, turn, whosWon, user, quanCo );
			infoObject.setBName( player1Name );
			infoObject.setWName( player2Name );
			listInfoObject.add( infoObject );
		}

		return XMLHelper
				.convertListObjectToXML( listInfoObject, processName, ChessBoardInfo.class );
	}
	
	private String convertToXMLString( ArrayList<QuanCo> listQuanCo,
			String processName, ChatUser user, Integer isTablesOwner, String player1Name,
			String player2Name, String status, int turn, int whosWon ) {
		
		ArrayList<ChessBoardInfo> listInfoObject = new ArrayList<ChessBoardInfo>();
		ChessBoardInfo infoObject;
		QuanCo quanCo;

		for ( int i = 0; i < listQuanCo.size(); i++ ) {
			quanCo = listQuanCo.get( i );

			infoObject = new ChessBoardInfo( status, turn, whosWon, user, quanCo );
			infoObject.setBName( player1Name );
			infoObject.setWName( player2Name );
			infoObject.setIsTOwner( isTablesOwner );
			listInfoObject.add( infoObject );
		}

		return XMLHelper
				.convertListObjectToXML( listInfoObject, processName, ChessBoardInfo.class );
	}

	/**
	 * Nuoc di thu 2
	 * 
	 * @param oDangChon
	 * @param turn
	 * @return
	 */
	public int selectAPiece( Rectangle oDangChon, int turn ) {
		repaintArea.clear();
		for ( int i = 0; i < mListQuanCo.size(); i++ ) {
			if ( ( mListQuanCo.get( i ).isInSelectedArea( oDangChon ) ) ) {
				if ( ( mListQuanCo.get( i ).color == turn ) ) {
					// Them mot o can ve lai
					repaintArea.add( oDangChon );
					return i;
				}
			}
		}

		return Const.UNDEFINE_VALUE;
	}

	/**
	 * Chon mot quan co o o bat ky - dung cho nuoc di dau tien
	 */
	public boolean moveAPiece( int whichPiece, Rectangle destination,
			Component dialogParent ) {

		QuanCo pieceChosen = mListQuanCo.get( whichPiece );

		// Tha quan
		if ( releasePiece( whichPiece, destination ) ) {
			return true;
		}

		QuanCo foundedPiece = null;
		int foundedIdx = Const.UNDEFINE_VALUE;

		for ( int i = 0; i < mListQuanCo.size(); i++ ) {
			if ( whichPiece != i ) {
				if ( ( mListQuanCo.get( i ).isInSelectedArea( destination ) ) ) {
					foundedPiece = mListQuanCo.get( i );
					foundedIdx = i;
				}
			}
		}

		boolean canmove = pieceChosen
				.canMove( board, destination, foundedPiece, mListQuanCo );

		// TODO for test
//		 boolean canmove = true;

		// Di chuyen neu co the
		if ( canmove ) {
			repaintArea.addAll( currentStepHistory );
			currentStepHistory.clear();
			currentStepHistory.add( pieceChosen.toaDo );

			// Kiem tra xem quan do da vao vung phong quan hay chua
			if ( board.isInUpgradeZone( destination, pieceChosen.color ) ) {

				// neu quan do co kha nang phong quan
				if ( pieceChosen.canUpgrade() ) {
					int selectedValue = JOptionPane.OK_OPTION;

					if ( !pieceChosen
							.isTrongVungBatBuocPhongQuan( board, destination ) ) {
						selectedValue = JOptionPane
								.showConfirmDialog( dialogParent, Msg.PHONG_CAP_KHONG );
					}

					// Neu bam vao nut Ok thi phong quan
					if ( selectedValue == JOptionPane.OK_OPTION ) {
						pieceChosen.upgrade( destination, mListQuanCo );
						
						pieceChosen = mListQuanCo.get( whichPiece );											
					}
				}
			}

			pieceChosen.move( board, destination, foundedIdx, mListQuanCo );
			
			// Update nha tu
			if( foundedIdx != Const.UNDEFINE_VALUE ) {
				updateSoLuongTuBinh( mListQuanCo );	
				repaintArea.add( mListQuanCo.get( foundedIdx ).toaDo );
			}
			
			currentStepHistory.add( pieceChosen.toaDo );
//			repaintArea.add( pieceChosen.toaDo );
			repaintArea.addAll( currentStepHistory );

			return true;
		}

		return false;
	}

	public boolean isHetCo( int whichSide ) {
		return CommonMethod.isHetCo( board, mListQuanCo, whichSide );
	}

	public ArrayList<Rectangle> taiHienListQuanCo(
			ArrayList<ChessBoardInfo> listInfo, boolean normalDirection ) {

//		repaintArea.clear();
//		repaintArea.addAll( historyForRepaint );
//		historyForRepaint.clear();

		createListHistory( listInfo, normalDirection );

		showNext( listH, mListQuanCo );

//		repaintArea.addAll( historyForRepaint );

		return repaintArea;
	}

	public ArrayList<Integer> createListHistory(
			ArrayList<ChessBoardInfo> listInfo, boolean normalDirection ) {
		return createListHistory( listInfo, mListQuanCo, normalDirection );
	}

	public ArrayList<Integer> createListHistory( String xmlInfo,
			ArrayList<QuanCo> oldList, boolean normalDirection ) {
		@SuppressWarnings( "unchecked" )
		ArrayList<ChessBoardInfo> listInfo = ( ArrayList<ChessBoardInfo> ) XMLHelper
				.convertXMLToListObject( xmlInfo, ChessBoardInfo.class );

		return createListHistory( listInfo, oldList, normalDirection );
	}

	public ArrayList<Integer> createListHistory(
			ArrayList<ChessBoardInfo> listInfo, ArrayList<QuanCo> oldList,
			boolean normalDirection ) {
		listH.clear();		
		repaintArea.clear();
		repaintArea.addAll( currentStepHistory );
		currentStepHistory.clear();
		
		ArrayList<Integer> listIdx = new ArrayList<Integer>();
		ChessBoardInfo info;
		QuanCo quanCo;		
		for ( int i = 0; i < oldList.size(); i++ ) {
			info = listInfo.get( i );
			quanCo = oldList.get( i );

			// Neu co su dich chuyen vi tri quan co thi ve lai
			if ( hasChanged( quanCo, info ) ) {

				listIdx.add( i );
				// Them lich su cua nuoc di
				H h = new H( i, quanCo, info );

				listH.add( h );
				if( info.getIsTB() == Const.FALSE ) {
					currentStepHistory.add( quanCo.toaDo );
					currentStepHistory.add( board.getRect( info.x, info.y ) );
				}
			}
		}
		
		setCurrentStep();
		
		return listIdx;
	}

	public boolean releasePiece( int whichPiece, Rectangle destination ) {

		QuanCo selectedPiece = mListQuanCo.get( whichPiece );

		// Tha quan
		if ( selectedPiece.isTuBinh ) {
			if ( selectedPiece.canRelease( board, destination, mListQuanCo ) ) {

				// Lay o can ve lai truoc khi tha
				repaintArea.add( selectedPiece.toaDo );

				// Tha quan
				selectedPiece.release( board, destination );

				// Ve lai o noi den
				repaintArea.add( selectedPiece.toaDo );
				return true;
			}
		}

		return false;
	}

	/**
	 * 0: Trang thai 1 la trang thai ban dau step = 0: tu trang thai ban dau di
	 * len mot nuoc 1: chuyen sang trang thai 1 step = 1: tu trang thai 1 di len
	 * mot nuoc 2: chuyen sang trang thai 2 step = 2:...
	 */
	@SuppressWarnings( "unchecked" )
	public void showNext() {
		
		step++;
		System.out.println( "Next: " + step );

		String his = boardHistory.get( step );
		
		ArrayList<H> list = ( ArrayList<H> ) XMLHelper
				.convertXMLToListObject( his, H.class );
		
		showNext( list, listQuanCoForHistory );		
	}
	
	public void showNext( ArrayList<H> list, ArrayList<QuanCo> listQuanCo ) {

//		repaintArea.clear();

		if ( !list.isEmpty() ) {
			for ( H hist : list ) {

				int idx = hist.getIdx();

				// Truong hop phong cap hoac bi bat quan
				if ( !hist.getOldC().equals( hist.getNewC() )
						|| !hist.getOldN().equals( hist.getNewN() ) ) {

					QuanCo quanCoMoi = getNewInstanceOfQuanCo( mainApplet, hist.getNewN(), normalDirection, hist
							.getNewC() );

					listQuanCo.remove( idx );
					listQuanCo.add( idx, quanCoMoi );
				}

				QuanCo quanCo = listQuanCo.get( idx );

				// Cap nhat toa do
				quanCo.toaDo = board.getRect( hist.getNewX(), hist.getNewY() );
				
				if( !hist.getOldTb().equals( hist.getNewTb() ) ) {
					if( hist.getNewTb() == Const.TRUE ) {
						quanCo.isTuBinh = true;	
					}else {
						quanCo.isTuBinh = false;
					}
				}
			}
			
			updateSoLuongTuBinh( listQuanCo );
			
			setAreaForRepaint( list );
		}
	}

	@SuppressWarnings( "unchecked" )
	public void showPrevious() {

		String his = boardHistory.get( step );

		ArrayList<H> list = ( ArrayList<H> ) XMLHelper
				.convertXMLToListObject( his, H.class );

		repaintArea.clear();

		if ( !list.isEmpty() ) {
			for ( H hist : list ) {
				int idx = hist.getIdx();

				// Neu quan nay vua bi bat lam tu binh
				if ( !hist.getOldC().equals( hist.getNewC() )
						|| !hist.getOldN().equals( hist.getNewN() ) ) {

					QuanCo quanCoMoi = getNewInstanceOfQuanCo( mainApplet, hist.getOldN(), normalDirection, hist
							.getOldC() );

					listQuanCoForHistory.remove( idx );
					listQuanCoForHistory.add( idx, quanCoMoi );
				}

				QuanCo quanCo = listQuanCoForHistory.get( idx );

				quanCo.toaDo = board.getRect( hist.getOldX(), hist.getOldY() );

				if( !hist.getOldTb().equals( hist.getNewTb() ) ) {
					if( hist.getOldTb() == Const.TRUE ) {
						quanCo.isTuBinh = true;	
					}else {
						quanCo.isTuBinh = false;
					}					
				}				
			}
			
			updateSoLuongTuBinh( listQuanCoForHistory );	
			
			setAreaForRepaint( list );
		}

		System.out.println( "Prev: " + step );
		step--;
	}

	private void updateSoLuongTuBinh( ArrayList<QuanCo> listQuanCo ) {
		board.resetSoLuongTuBinh();

		for ( QuanCo quanCo : listQuanCo ) {
			if ( quanCo.isTuBinh ) {
				Point toaDo = board.getToaDoNhaTu( quanCo.toaDo );
				board.tangSoLuongTuBinh( toaDo );
			}
		}
	}

	private boolean hasChanged( QuanCo quanCo, ChessBoardInfo info ) {
		return quanCo.toaDo.x != info.x || quanCo.toaDo.y != info.y;
	}

	private QuanCo getNewInstanceOfQuanCo( JApplet codeBase, String className,
			boolean nomarlDirection, Integer color2 ) {
		try {
			Class<?> cls = Class.forName( Const.PACKAGE_NAME + className );

			// Khai bao cac kieu du lieu cho param cua constructor
			Class<?> paramType[] = new Class[4];
			paramType[0] = Rectangle.class;
			paramType[1] = Integer.TYPE;
			paramType[2] = Boolean.TYPE;
			paramType[3] = JApplet.class;

			// Lay ra constructor
			Constructor<?> ct = cls.getConstructor( paramType );

			// Get new instance of this class
			Object argList[] = new Object[4];

			argList[0] = new Rectangle();
			argList[1] = color2;
			argList[2] = nomarlDirection;
			argList[3] = codeBase;

			QuanCo quanCo = ( QuanCo ) ct.newInstance( argList );

			return quanCo;
		} catch ( Exception e ) {
			throw new RuntimeException();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#clone()
	 */
	public ArrayList<QuanCo> clone() {
		return CommonMethod.cloneListQuanCo( mListQuanCo );
	}
	
	public ArrayList<QuanCo> getListQuanCo() {
		return mListQuanCo;
	}

	public ArrayList<Rectangle> getRepaintArea() {
		return repaintArea;
	}

	public ArrayList<Rectangle> getHistory() {
		return currentStepHistory;
	}

	public ArrayList<H> getListH() {
		return listH;
	}

	public ArrayList<String> getBoardHistory() {
		return boardHistory;
	}

	public int getStep() {
		return step;
	}

	public void addHistory() {
		if( !listH.isEmpty() ) {
			boardHistory.add( XMLHelper
					.convertListObjectToXML( listH, Const.HISTORY_PROCESS, H.class ) );	
		}
	}

	public void addHistory( String history ) {
		boardHistory.add( history );
	}

	public void setCurrentStep() {
		step = boardHistory.size() - 1;
	}

	public int getCurrentStep() {
		return boardHistory.size() - 1;
	}
	
	public boolean isCurrentStep() {
		return step == boardHistory.size() - 1;
	}

	public void setBeginStep() {
		step = 0;
	}	
	
	public void setHistoryInCurrentStatus() {
		listQuanCoForHistory = clone();
		updateSoLuongTuBinh( listQuanCoForHistory );
		setCurrentStep();
	}
	
	public void setHistoryInInitStatus() {
		listQuanCoForHistory = CommonMethod.cloneListQuanCo( listQuanCoWhenInit );
		updateSoLuongTuBinh( listQuanCoForHistory );
		step = -1;
	}
	
	public void testShowHistoryString() {
		int i = 0;
		System.out.println( "-------------------------------------" );
		for( String xml : boardHistory ) {
			System.out.println( "Step " + i + " :" + xml );
			i++;
		}
		System.out.println( "Current Step:" + step );
		System.out.println( "-------------------------------------" );
	}
	
	
	public String getInitStatusOfBoard( String processName, ChatUser user,
			String status, String player1Name, String player2Name, int turn, int whosWon ) {

		return convertToXMLString( CommonMethod.cloneListQuanCo( listQuanCoWhenInit ), processName, user, status, turn, whosWon );
	}
	
	public String getInitStatusOfBoard( String processName, ChatUser user,
			String player1Name, String player2Name ) {		
		
		return convertToXMLString( CommonMethod.cloneListQuanCo( listQuanCoWhenInit ), processName, user, player1Name, player2Name, Const.STATUS_IDLE, Const.UNDEFINE_VALUE, Const.UNDEFINE_VALUE );
	}
	
	public String getInitStatusOfBoard( String processName, ChatUser user, Integer isTableOwner, String player1Name, String player2Name ) {		
		
		return convertToXMLString( CommonMethod.cloneListQuanCo( listQuanCoWhenInit ), processName, user, isTableOwner, player1Name, player2Name, Const.STATUS_IDLE, Const.UNDEFINE_VALUE, Const.UNDEFINE_VALUE );
	}
	
	
	
	public void setAreaForRepaint(){
		
		for( H h : listH ) {
			repaintArea.add( board.getRect( h.getOldX(), h.getOldY() ) );
			repaintArea.add( board.getRect( h.getNewX(), h.getNewY() ) );
		}
	}
	
	public void setAreaForRepaint( ArrayList<H> listHist ){
		for( H h : listHist ) {
			repaintArea.add( board.getRect( h.getOldX(), h.getOldY() ) );
			repaintArea.add( board.getRect( h.getNewX(), h.getNewY() ) );
		}
	}
}
